package com.giw.uima.annotator;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.uima.TokenAnnotation;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.util.Level;

import com.giw.uima.ts.CompetitionAnnotation;


public class CompetitionAnnotator extends JCasAnnotator_ImplBase{

	private final String COMPETITIONDICT_PATH="dictionary_competition";

	private List<String> competition;
	@Override
	public void initialize(UimaContext aContext) throws ResourceInitializationException {
		super.initialize(aContext);
		try {
			this.competition = IOUtils.readLines(new FileInputStream(String.valueOf(aContext
					.getConfigParameterValue(COMPETITIONDICT_PATH))));
			Collections.sort(competition); // sort collection to make binary search possible
		} catch (IOException e) {
			e.printStackTrace();
			aContext.getLogger().log(Level.SEVERE, "error reading dictionary competition file");
			throw new ResourceInitializationException(e);
		}
	}

	@Override
	public void process(JCas jcas) throws AnalysisEngineProcessException {

		FSIterator<Annotation> iterator=jcas.getAnnotationIndex(TokenAnnotation.type).iterator();
		Annotation left=null;
		Annotation middle=null;
		Annotation right = null;
		boolean isAnnotation = false;
		String word1=null;
		String word2=null;
		String word3=null;
		int remainingAnnotation=this.remainsAnnotation(iterator);
		int num_Annotation=this.countAnnotation(iterator);
		
		if(num_Annotation==2){
			middle=iterator.get();
			iterator.moveToNext();
			right=iterator.get();
			iterator.moveToNext();
		}
		if(num_Annotation==1){
			this.createAnnotation(iterator.get().getBegin(), iterator.get().getEnd(), 
					iterator.get().getCoveredText(), jcas);
			return;
		}
		if(remainingAnnotation>=3) {
		iterator.moveToNext();
		iterator.moveToNext();
		}

		while(iterator.hasNext()){
			isAnnotation = false;
			right=iterator.get();
			iterator.moveToPrevious();
			middle=iterator.get();
			iterator.moveToPrevious();
			left = iterator.get();
			iterator.moveToNext();
			iterator.moveToNext();

			word1=left.getCoveredText();
			word2=middle.getCoveredText();
			word3 =right.getCoveredText();

			if(isUP(left)&&isUP(right)){
				isAnnotation = 
					this.createAnnotation(left.getBegin(), right.getEnd(), word1+" "+word2+" "+word3, jcas);
				if(isAnnotation){
					switch(this.remainsAnnotation(iterator)){
					case 2:
						iterator.moveToNext();
						middle=iterator.get();
						iterator.moveToNext();
						right=iterator.get();
						iterator.moveToNext();
						break;
					case 1:
						middle=right;
						iterator.moveToNext();
						right=iterator.get();
						iterator.moveToNext();
						break;
					case 0:
						iterator.next();
						break;
					default:
						this.moveIterator(iterator, 3);
						break;
					}
				}
			}
			if(!isAnnotation){
				if(isUP(left)&&isUP(middle)){
					isAnnotation = this.createAnnotation(left.getBegin(), middle.getEnd(),word1+" "+word2,
							jcas);
				}
				if(!isAnnotation&&isUP(left)){
					this.createAnnotation(left.getBegin(), left.getEnd(), word1, jcas);
				}
				this.moveIterator(iterator, 1);}
		}
		if(!isAnnotation&&isUP(middle)&&isUP(right)){
			isAnnotation = this.createAnnotation(middle.getBegin(), right.getEnd(),middle.getCoveredText()+" "+right.getCoveredText()
					, jcas);
		}
		if(!isAnnotation&&isUP(right)){
			isAnnotation = this.createAnnotation(right.getBegin(), right.getEnd(), right.getCoveredText(), jcas);
		}
		if(!isAnnotation&&isUP(middle)){
			isAnnotation = this.createAnnotation(middle.getBegin(), middle.getEnd(), middle.getCoveredText(), jcas);
		}
	}



	private boolean isUP(Annotation annotation) {
		String text=annotation.getCoveredText();
		Character c=text.charAt(0);
		return Character.isUpperCase(c);
	}

	private boolean createAnnotation(int begin,int end,String text,JCas jcas){
		if(Collections.binarySearch(this.competition, text)>=0){
			CompetitionAnnotation competitionAnnotation = new CompetitionAnnotation(jcas);
			competitionAnnotation.setBegin(begin);
			competitionAnnotation.setEnd(end);
			competitionAnnotation.addToIndexes();
			return true;
		}
		return false;
	}

	private int remainsAnnotation(FSIterator<Annotation> i){
		int a = 0;
		i.moveToNext();
		while(i.hasNext()){
			a++;
			i.next();
		}
		int b = a;
		while(a>0)
		{
			i.moveToPrevious();
			a--;
		}
		i.moveToPrevious();
		return b;
	}
	private void moveIterator(FSIterator<Annotation> iter,int step){
		int i;
		for(i=0;i<step;i++){
			iter.moveToNext();
		}
	}
	private int countAnnotation(FSIterator<Annotation> iter){
		int a=0;
		while(iter.hasNext()){
			a++;
			iter.moveToNext();
		}
		int b=a;
		while(b>0){
			b--;
			iter.moveToPrevious();
		}
		return a;
	}
}

